#!/usr/bin/python3
# -*- coding: utf-8 -*-
'''
@Author: Phoenix
@Date: 2020-08-10 23:33:35
'''

from os import path
from sys import exit
from time import sleep

from modules.utils import (
    BASE_ABSPATH,
    GLOBAL_DATA,
    MY_ERROR_CODES,
    TODO_MARK,
    enpun_2_zhpun,
    print_err,
    read_json,
    remove_escape,
)

# 翻译引擎字典
_API_TYPES = {
    '1': '百度翻译（高级版每月免费100W字符，超出收费）',
    '2': '腾讯翻译君（每月免费500W字符）',
    '3': '谷歌翻译（第三方）',
    '4': '彩云小译（收费）',
    '5': '有道智云（收费）',
    '6': 'DeepL翻译（第三方，最精准，可能需要梯子）',
}

# 译文库
TRANSLATED_LIB_LIBRARY = 'TransLib.json'


class Interpreter:
    '''
    翻译机


    初始化：

    _interpreter = Interpreter(from_lang, to_lang)

    配置翻译机:

    _interpreter.configure_tool()
    '''

    def __init__(self, from_lang='auto', to_lang=''):

        # 当前启用的API
        self._curr_api = None

        # 源语种
        self._from_lang = from_lang
        # 目标语种
        self._to_lang = to_lang
        # 请求频率
        self._rate = 1

        # 调用API种类
        self._api_type = '1'

        # 读取译文库文本
        self._translation_library = read_json(
            path.join(BASE_ABSPATH, 'libraries', TRANSLATED_LIB_LIBRARY)
        )

    def configure_tool(self):
        '''
        配置翻译机
        '''

        self._select_api_type()
        self._get_interpreter()
        self._select_lang_type()

    def translate_txt(self, source_txt='', open_todo=GLOBAL_DATA['todo_mark']) -> str:
        '''
        翻译文本

        - source_txt: 输入文本
        - open_todo: 是否在句首添加TODO标记，默认由config配置
        '''

        if source_txt.strip() == '':
            print_err('原文为空字串！\n')
            return source_txt

        print(f'原文：{source_txt}')

        target = ''
        # 译文库中有该文本，且该文本是否不为空时，直接返回译文库中文本
        if (
            source_txt in self._translation_library
            and self._translation_library[source_txt] != ''
        ):
            target = self._translation_library[source_txt]
            print(f'库译文：{target}\n')
            return target

        # 若译文库中无该文本，则发起翻译请求
        # 挂起程序指定秒数，避免超过翻译API的请求频率
        sleep(1 / self._rate)

        # 删除转义符
        source_txt_new = remove_escape(source_txt)

        # 调用api接口翻译
        target = self._curr_api.translate(
            source_txt_new, self._to_lang, self._from_lang
        )

        # 翻译api返回的字符串可能存在一些\u开头的，但无法使用utf-8解码的字符串
        # encode函数遇此问题默认是抛异常，这里修改参数调整为将字符串替换成“?”
        target = target.encode('utf-8', 'replace').decode('utf-8')

        if not target in MY_ERROR_CODES:
            target = enpun_2_zhpun(target)
            print(f'译文：{target}\n')
            if open_todo:
                target = TODO_MARK + target
        return target

    def translate_single_txt(self, source_txt='') -> str:
        '''
        翻译单语句

        - source_txt: 输入文本
        '''

        if source_txt.strip() == '':
            print_err('原文为空字串！\n')
            return source_txt

        target = ''
        # 译文库中有该字段，且该字段是否不为空时，直接返回译文库中文本
        if (
            source_txt in self._translation_library
            and self._translation_library[source_txt] != ''
        ):
            target = self._translation_library[source_txt]
            print(f'库译文：{target}')
            return target

        # 删除转义符
        source_txt_new = remove_escape(source_txt)
        target = self._curr_api.translate(
            source_txt_new, self._to_lang, self._from_lang
        )

        # 翻译api返回的字符串可能存在一些\u开头的，但无法使用utf-8解码的字符串
        # encode函数遇此问题默认是抛异常，这里修改参数调整为将字符串替换成“?”
        target = target.encode('utf-8', 'replace').decode('utf-8')

        if not target in MY_ERROR_CODES:
            target = enpun_2_zhpun(target)
            print(f'译文：{target}')
        return target

    def _get_interpreter(self):
        '''
        实例化翻译器
        '''

        # 百度
        if self._api_type == '1':
            import modules.api.baidu.baidu as baidu

            self._curr_api = baidu.BaiduTranslation('baidu_api')

        # 腾讯
        elif self._api_type == '2':
            import modules.api.tencent.tencent as tencent

            self._curr_api = tencent.TencentTranslation('tencent_api')

        # 谷歌
        elif self._api_type == '3':
            import modules.api.google.google as google

            self._curr_api = google.GoogleTranslation('google_api')

        # 彩云小译
        elif self._api_type == '4':
            import modules.api.caiyun.caiyun as caiyun

            self._curr_api = caiyun.CaiyunTranslation('caiyun_api')

        # 有道
        elif self._api_type == '5':
            import modules.api.youdao.youdao as youdao

            self._curr_api = youdao.YoudaoTranslation('youdao_api')

        # DeepL
        elif self._api_type == '6':
            import modules.api.deepl.deepL as deepL

            self._curr_api = deepL.DeepLTranslation('deepl_api')

        else:
            print_err('未找到相应翻译器！')
            exit(0)

        self._rate = self._curr_api.get_rate()

    def _select_api_type(self, reselect=False, serial_num='1'):
        '''
        选择翻译引擎

        - reselect: 是否为重新选择
        - serial_num: 选定的操作序号
        '''

        if not reselect:
            str_api = '''
翻译引擎列表如下：
'''
            for k, v in _API_TYPES.items():
                str_api += f'{k}) {v}\n'
            print(str_api)

            default = list(_API_TYPES.keys())[0]
            _inp = input(f'请选择翻译引擎，直接回车默认选{default}：').strip()
            if _inp == '':
                print(
                    f'''
======================================================================
当前翻译引擎：【{_API_TYPES[default]}】'''
                )
                self._api_type = default
                return

            if not _inp in _API_TYPES:
                self._select_api_type(True, _inp)
                return

            print(
                f'''
======================================================================
当前翻译引擎：【{_API_TYPES[_inp]}】'''
            )
            self._api_type = _inp
            return

        _tmp = input(
            f'引擎列表中不存在序号 {serial_num}，请重新输入正确序号或回车退出程序：'
        ).strip()
        if _tmp == '':
            exit(0)

        if not _tmp in _API_TYPES:
            self._select_api_type(True)
            return

        print(
            f'''
======================================================================
当前翻译引擎：【{_API_TYPES[_tmp]}】'''
        )
        self._api_type = _tmp

    def _select_lang_type(self, reselect=False, serial_num='', lang_dict: dict = {}):
        '''
        选择目标语种

        - reselect: 是否为重新选择
        - serial_num: 选定的操作序号
        - lang_dict: 语种字典
        '''

        # 实例化对象时传入了翻译语种，就无需再选择一次
        if self._to_lang != '':
            return

        # 当前语种词典
        curr_lang_dict = lang_dict

        if not reselect:
            # 获取目标语种
            curr_lang_dict = self._curr_api.get_to_langs()
            if len(curr_lang_dict) < 1:
                print_err('语言字典为空！')
                exit(0)

            str_lang = '''
要翻译成哪种语言？
'''
            for k, v in curr_lang_dict.items():
                str_lang += f'{k}) {v['n']}\n'
            print(str_lang)

            default = list(curr_lang_dict.keys())[0]
            _inp = input(f'请选择目标语种，直接回车默认选{default}：').strip()
            if _inp == '':
                print(
                    f'''
======================================================================
当前目标语种：【{curr_lang_dict[default]['n']}】'''
                )
                self._to_lang = curr_lang_dict[default]['c']
                return

            if not _inp in curr_lang_dict:
                self._select_lang_type(True, _inp, curr_lang_dict)
                return

            print(
                f'''
======================================================================
当前目标语种：【{curr_lang_dict[default]['n']}】'''
            )
            self._to_lang = curr_lang_dict[_inp]['c']
            return

        _tmp = input(
            f'语种列表中不存在序号 {serial_num}，请重新输入正确序号或回车退出程序：'
        ).strip()
        if _tmp == '':
            exit(0)

        if not _tmp in curr_lang_dict:
            self._select_lang_type(True, _tmp, curr_lang_dict)
            return

        print(
            f'''
======================================================================
当前目标语种：【{curr_lang_dict[_tmp]['n']}】'''
        )
        self._to_lang = curr_lang_dict[_tmp]['c']
